package com.cloud.logger.zchain.core.zookeeper;

import com.cloud.logger.zchain.core.common.properties.ServerInfo;
import com.cloud.logger.zchain.core.constants.Constants;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.*;
import java.util.concurrent.CountDownLatch;

/**
 * Created by Administrator on 2017/12/15.
 */
public class LeaderElection {
    private static CuratorFramework zk;
    private int sessionTimeout;

    private static byte[] DEFAULT_DATA = {0x12,0x34};
    private static Object mutex = new Object();

    private static String ROOT;

    private byte[] localhost = getLocalIpAdressBytes();

    private String znode;

    private static CountDownLatch firstElectionSignal = new CountDownLatch(1);

    //----------------------------------------------------
    // leader的IP地址
    //----------------------------------------------------
    private static String leader;

    public LeaderElection() throws Exception {
        synchronized(this) {
            ROOT = Constants.SEPARATOR + Constants.MONOPOLY;
            this.zk = ZookeeperFactory.getInstance().getZkTools();
            ensureExists(ROOT);
            ensureLocalNodeExists();
        }
    }

    /**
     * 检查本机是否已创建节点，不存在则创建
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void ensureLocalNodeExists() throws Exception {
        List<String> list = zk.getChildren().forPath(ROOT);

        String path;
        for (String node : list) {
            path = ROOT + "/" + node;
            if (path.equals(ServerInfo.scheduleNode)) {
                znode = path;
                break;
            }
        }

//        if(znode==null){
//            znode = ZookeeperFactory.getInstance().createServerEphemeralSequentialNode();
//        }
    }

    public void ensureExists(String path) {
        try {
            Stat stat = zk.checkExists().forPath(path);
//            if (stat == null) {
//                znode = ZookeeperFactory.getInstance().createServerEphemeralSequentialNode();
//            }
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void start() throws Exception {
        new LeaderElection();
        List<String> nodes = zk.getChildren().forPath(ROOT);
        SortedSet<String> sortedNode = new TreeSet<String>();
        for (String node : nodes) {
            sortedNode.add(ROOT + "/" + node);
        }
        //----------------------------------------------------
        // 取出序列号最小的消息
        //----------------------------------------------------
        String first = sortedNode.first();
        leader = first;

    }

    /**
     * 获取本地内网IP地址
     * @return
     * @throws SocketException
     */
    public static String getLocalIpAddress() throws SocketException {
        // 获得本机的所有网络接口
        Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();

        while (nifs.hasMoreElements()) {
            NetworkInterface nif = nifs.nextElement();

            // 获得与该网络接口绑定的 IP 地址，一般只有一个
            Enumeration<InetAddress> addresses = nif.getInetAddresses();
            while (addresses.hasMoreElements()) {
                InetAddress addr = addresses.nextElement();

                String ip = addr.getHostAddress();
                // 只关心 IPv4 地址
                if (addr instanceof Inet4Address && !"127.0.0.1".equals(ip)) {
                    return ip;
                }
            }
        }
        return null;
    }

    public static byte[] getLocalIpAdressBytes() throws SocketException {
        return ServerInfo.ipPortByte;
    }

    public static String getLeader() throws Exception {
        start();
        return leader;
    }

    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {

    }
}
